package org.huang.zhen;

public class GameController implements GameMap.GameMapListener {
    private static final float BLOCK_DOWN_ACCELERATE_RATIO = 0.1f;
    private static final int SCALE_FOR_SCORE = 10;
    private static final int LEVEL_GAP = SCALE_FOR_SCORE * 5;
    private static final int SPEED_MAX = 100;
    private static final int SPEED_LEVEL_GAP = 50;
    private final int BLOCK_DOWN_SPEED_DEFAULT = 600;
    private GameMap mGameMap;
    private Block   mCurrentBlk;
    private Block   mNextBlk;
    private GameChangeListener mListener;
    private int mScore;
    private int mLevel;
    private boolean isAccelerating;

    public interface GameChangeListener {
        public void onGameMapChanged(int [][]map);
        public void onNextBlockChanged(int [][]map);
        public void onScoreChanged(int score);
        public void onLevelChanged(int level);
    }

    public GameController(GameChangeListener listener) {
        mGameMap = new GameMap(this, BLOCK_DOWN_SPEED_DEFAULT);
        mListener = listener;
        mScore = 0;
        mLevel = 0;
        isAccelerating = false;
    }

    public void startGame() {
        mCurrentBlk = BlockFactory.getGeneralBlock();
        mNextBlk = BlockFactory.getGeneralBlock();
        mGameMap.insertBlock(mCurrentBlk);
        mGameMap.start();
        mListener.onNextBlockChanged(mNextBlk.getMap());
    }

    public void pauseGame() {
        mGameMap.pause();
    }

    public void continueGame() {mGameMap.resume();}

    public void stopGame() {
        try {
            mGameMap.stop();
        }catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public void moveBlock2Left() {
        mGameMap.changeBlockHorizonPos(GameMap.GAME_BLOCK_HORIZONTAL_DIRECTION.LEFT);
    }

    public void moveBlock2Right() {
        mGameMap.changeBlockHorizonPos(GameMap.GAME_BLOCK_HORIZONTAL_DIRECTION.RIGHT);
    }

    public void setAccelerateDown(boolean isNeedAccelerate) {

        // 加速中，要求恢复原来的速度
        if (isAccelerating && !isNeedAccelerate) {
            int currentSpeed = mGameMap.getSpeed();
            mGameMap.setDownSpeed((int)(currentSpeed / BLOCK_DOWN_ACCELERATE_RATIO));
            isAccelerating = false;
            return;
        }

        // 正常速度要求加速
        if (!isAccelerating && isNeedAccelerate) {
            mGameMap.setDownSpeed((int)(mGameMap.getSpeed() * BLOCK_DOWN_ACCELERATE_RATIO));
            isAccelerating = true;
        }
    }

    public void rotateBlock() {
        mGameMap.rotateBlock();
    }
    @Override
    public void onGameMapChanged(int[][] gameMap) {
        if (mListener != null) {
            mListener.onGameMapChanged(gameMap);
        }
    }

    private void changeSpeed(int level) {
        int currentSpeed = mGameMap.getSpeed();
        currentSpeed = currentSpeed - (level - 1) * SPEED_LEVEL_GAP;
        if (currentSpeed < SPEED_MAX) {
            currentSpeed = SPEED_MAX;
        }
        mGameMap.setDownSpeed(currentSpeed);
    }

    @Override
    public void onLinesRemoved(int lines) {
        mScore += lines * SCALE_FOR_SCORE;
        if (mListener == null) {
            return;
        }
        mListener.onScoreChanged(mScore);
        if (mScore > mLevel * LEVEL_GAP) {
            mLevel++;
            changeSpeed(mLevel);
            mListener.onLevelChanged(mLevel);
        }
    }

    @Override
    public void onBlockSettled() {
        mGameMap.insertBlock(mNextBlk);
        mNextBlk = BlockFactory.getGeneralBlock();
        mListener.onNextBlockChanged(mNextBlk.getMap());
    }
    @Override
    public void onMapFull() {
        stopGame();
    }
}
